/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using MyPhotoIndex.Utilities;
using System.Threading;
using MyPhotoIndex.ImageBank;
using MyPhotoIndex.Utilities.ImageMetaData;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.Plugins.ImageFormatProviders;
using MyPhotoIndex.Importer.Properties;
using MyPhotoIndex.Interfaces.Imaging;
using MyPhotoIndex.Interfaces.ImageFormatProviders;

namespace MyPhotoIndex.Importer
{
    public class ImageFileCollection : IImageCollection , IDisposable
    {
        private StringCollection             m_filesList;
        private Dictionary<int, IImageData>  m_imageDataCache;
        private Semaphore                    m_imageLoadSemaphore;

        public ImageFileCollection(string[] filesList)
        {
            m_imageLoadSemaphore = new Semaphore(3, 3);
            m_filesList = new StringCollection();
            m_filesList.AddRange(filesList);
            m_imageDataCache = new Dictionary<int, IImageData>();

            int imageId = 0;
            foreach (string fileName in m_filesList)
            {
                IImageData imageData = new ImportImageData();
                imageData.Id = imageId;
                imageData.FileName = fileName;
                m_imageDataCache.Add(imageId++, imageData);
            }
        }

        public IImageData this[int imageId]
        {
            get
            {
                IImageData imageData = null;
                if (m_imageDataCache.TryGetValue(imageId, out imageData) == true)
                {
                    if (imageData.Thumbnail == null)
                    {
                        return LoadOneImageData(imageData);
                    }
                    else
                    {
                        return imageData;
                    }
                }

                return null;
            }
        }

        internal IImageData LoadOneImageData(IImageData fileImageData)
        {//Todo: image
      //      fileImageData.Thumbnail = Resources.sandclock_128;
            m_imageLoadSemaphore.WaitOne();
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetThumbnail), fileImageData);

            return fileImageData;
        }

        internal void GetThumbnail(Object state)
        {
            IImageData imageData = (IImageData)state;

            ExifExtractor exifInfo = null;
            IImageFormatProvider provider = imageData.FormatProvider;
            if (provider.IsVideo == false)
            {
                exifInfo = new ExifExtractor(imageData.FileName);
            }

            if (exifInfo != null)
            {
                imageData.DateTaken = exifInfo.DateTaken;
            }

            if (DateTime.Compare(imageData.DateTaken, DateTime.MinValue) == 0)
            {
                imageData.DateTaken = File.GetLastWriteTimeUtc(imageData.FileName);
            }

            try
            {
                imageData.Thumbnail = provider.GetThumbnail(imageData.FileName, new Size(240, 160));
                imageData.InvokeChangedEvent();
            }
            catch (Exception)
            {
                imageData.Thumbnail = null;
            }
            finally
            {
                m_imageLoadSemaphore.Release();
            }
        }

        public int Count
        {
            get { return m_filesList.Count; }
        }

        #region IDisposable Members

        public void Dispose()
        {
            foreach (IImageData imageData in m_imageDataCache.Values)
            {
                imageData.Dispose();
            }
        }

        #endregion

        #region IEnumerable<ImageData> Members

        public IEnumerator<IImageData> GetEnumerator()
        {
            return m_imageDataCache.Values.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        #region IImageCollection Members

        public event EventHandler<EventArgs> ImageCollectionLoadedEvent;

        public void Remove(int imageId)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void Remove(int imageId, bool deleteFromMedia)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IImageCollection Members


        public IImageData[] ToArray()
        {
            List<IImageData> list = new List<IImageData>(m_imageDataCache.Values);
            return list.ToArray();
        }

        #endregion
    }
}
